package com.warm.mini.wework.service.invoke;

import com.warm.mini.wework.config.WeworkConfigProperties;
import com.warm.mini.wework.service.invoke.handler.AbstractMsgHandler;
import com.warm.mini.wework.service.invoke.handler.BaseMsgHandler;
import com.warm.mini.wework.util.aes.AesException;
import com.warm.mini.wework.util.aes.WXBizMsgCrypt;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description 企微回调处理
 * @Author warmchuang
 * @Date 2022/2/8 18:33
 */
@Slf4j
@Service
public class WeworkInvokeServiceImpl {

    private ConcurrentHashMap<String, AbstractMsgHandler> msgHandlerMap = new ConcurrentHashMap<>();

    @Autowired
    public WeworkInvokeServiceImpl(List<AbstractMsgHandler> msgHandlers) {
        for (AbstractMsgHandler handler : msgHandlers) {
            msgHandlerMap.put(handler.resource(), handler);
        }
    }

    private AbstractMsgHandler getHandler(String resource){
        AbstractMsgHandler handler = msgHandlerMap.get(resource);
        if(Objects.isNull(handler)){
            handler = msgHandlerMap.get(BaseMsgHandler.BASE_RESOURCE);
        }
        return handler;
    }

    /**
     * 回调消息处理
     * @param msgSignature 企业微信加密签名
     * @param timestamp 时间戳
     * @param nonce 随机数
     * @param echostr 加密的字符串
     * @param xmlBody post 请求的 body
     * @param config
     */
    public Object invokeMsgHandle(String msgSignature, String timestamp, String nonce, String echostr,
                                  String xmlBody,
                                  WeworkConfigProperties config){
        WXBizMsgCrypt wxcpt = null;
        try {
            wxcpt = new WXBizMsgCrypt(config.getToken(), config.getEncodingAESKey(), config.getCorpId());
        } catch (AesException e) {
            log.info("get WXBizJsonMsgCrypt error:{}", e.getMessage(), e);
            return null;
        }

        if(StringUtils.isNotBlank(echostr)){
            return verifyUrl(msgSignature, timestamp, nonce, echostr, wxcpt);
        }

        // 解密消息
        if(Objects.nonNull(xmlBody)){
            String xmlMsg = decryptMsg(msgSignature, timestamp, nonce, xmlBody, wxcpt);
            // 异步消息处理
            CompletableFuture.runAsync(() -> {
                try {
                    getHandler(config.getResource()).handle(xmlMsg, config);
                } catch (Exception e){
                    log.info("handle msg error:{}", e.getMessage(), e);
                }
            });
        }
        return null;
    }

    private String decryptMsg(String msgSignature, String timestamp, String nonce, String xmlBody, WXBizMsgCrypt wxcpt){
        try {
            String decryptMsg = wxcpt.DecryptMsg(msgSignature, timestamp, nonce, xmlBody);
            log.info("decryptMsg:[{}]", decryptMsg);
            return decryptMsg;
        } catch (AesException e) {
            log.info("decryptMsg error:{}", e.getMessage(), e);
            return null;
        }
    }

    private String verifyUrl(String msgSignature, String timestamp, String nonce, String echostr, WXBizMsgCrypt wxcpt){
        // 配置回调时验证回调 url
        try {
            String verifyStr = wxcpt.VerifyURL(msgSignature, timestamp, nonce, echostr);
            log.info("verifyUrl result:{}", verifyStr);
            return verifyStr;
        } catch (AesException e) {
            log.info("verifyURL error:{}", e.getMessage(), e);
            return null;
        }
    }


}
